﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace tetris_data
{
    public class TetrisShape
    {
        public ShapeStruct Next { get; set; }
        public ShapeStruct Preview { get; set; }

        private ShapeStruct _ShapeArray;

        public ShapeStruct Shape
        {
            get
            {
                return _ShapeArray;
            }
            private set
            {
                _ShapeArray = value;
            }
        }

        public TetrisShape()
        {
            RandomShape();
        }

        /// <summary>
        /// 七种形状
        /// </summary>
        bool[][,] baseShapes = new bool[][,]{
            new bool[,]{{ true, true },  { true, true} },
            new bool[,]{{true},{true}, {true}, {true}},
            new bool[,]{{false, true, true}, {true, true, false}},
            new bool[,]{{true, true, false}, {false, true, true}},
            new bool[,]{{true, true, true}, {true, false, false}},
            new bool[,]{{true, true, true}, {false, false, true}},
           new bool[,] { { false, true, false }, {true, true, true}}
        };

        uint[] colors ={
            0xFFFF0000,
            0xFF00FF00,
            0xFF0000FF,
            0xFFFFFF00,
            0xFFFF00FF,
            0xFF00FFFF,
            0xFFEEEEEE
        };

        public uint ShapeColor { get { return Shape.Color; } }

        public bool[,] GridData { get; set; }

        public int Left { get { return Shape.Left; } set { Shape.Left = value; } }

        public int Top { get { return Shape.Top; } set { Shape.Top = value; } }


        public event Action CreatedNew;
        public void RandomShape()
        {
            var index = new Random().Next(baseShapes.Length);
            ShapeStruct shape = new ShapeStruct();
            shape.Data = baseShapes[index];
            shape.Color = colors[index];

            Random random = new Random();

            if (Shape == null)
            {
                Shape = shape;
                RandomShape();
            }
            else
            {
                Next = shape;
            }

            var d = random.Next(3);
            for (int r = 0; r < d; r++)
            {
                Next.ChangeDirection();
            }

            CreatedNew?.Invoke();
        }

        public void ChangeDirection()
        {
            Shape.ChangeDirection();
            Moved?.Invoke();
        }
        /// <summary>
        /// 形状矩阵
        /// </summary>
        bool[,] ShapeArray { get { return Shape.Data; } }

        public bool IsFull()
        {
            if (Top == 0)
            {
                for (var row = 0; row < ShapeArray.GetLength(0); row++)
                {
                    for (var col = 0; col < ShapeArray.GetLength(1); col++)
                    {
                        if (this.ShapeArray[row, col] && GridData[Top + row, Left + col])
                            return true;
                    }
                }
            }
            return false;
        }

        public event Action Moved;

        public void MoveDown()
        {
            if (!this.IsBottom())
            {
                Top += 1;
                Moved?.Invoke();
            }
            else
            {
                for (var row = 0; row < ShapeArray.GetLength(0); row++)
                {
                    for (var col = 0; col < ShapeArray.GetLength(1); col++)
                    {
                        if (ShapeArray[row, col])
                            this.GridData[Top + row, Left + col] = true;
                    }
                }

                Preview = Shape;
                Shape = Next;

                RandomShape();

                ReachedBottom?.Invoke();

            }
        }

        public bool IsBlock()
        {
            for (var row = 0; row < ShapeArray.GetLength(0); row++)
            {
                for (var col = 0; col < ShapeArray.GetLength(1); col++)
                {
                    //if (this.shapeGrid[row][col] == 1 && this.grid[this.top + row + 1][this.left + col] == 1)
                    //    return true;
                    if (Left > 0 && ShapeArray[row, col] && GridData[Top + row, Left + col - 1])
                        return true;
                    if ((Left + ShapeArray.GetLength(1)) < 10 && ShapeArray[row, col] && GridData[Top + row, Left + col + 1])
                        return true;
                }
            }
            return false;
        }

        public event Action ReachedBottom;
        public void MoveLeft()
        {
            if (this.Left > 0 && !this.IsBlock())
            {
                this.Left--;
                Moved?.Invoke();
            }
        }

        public void MoveRight()
        {
            if (Left + ShapeArray.GetLength(1) < 10 && !this.IsBlock())
            {
                this.Left++;
                Moved?.Invoke();
            }
        }

        public void Drop()
        {
            int slen = ShapeArray.GetLength(0);
            int ntop = 20 - slen;
            for (var row = Top; row < ntop; row++)
            {
                for (var scol = 0; scol < ShapeArray.GetLength(1); scol++)
                {
                    if (GridData[row + slen, Left + scol])
                    {
                        Top = row;
                        MoveDown();
                        return;
                    }
                }
            }
            Top = ntop ;
            MoveDown();
        }

        public void MoveQuickly()
        {
            if (!this.IsBottom())
            {
                this.Top += 1;
                Moved?.Invoke();
            }
        }
        bool IsBottom()
        {
            if (Top + ShapeArray.GetLength(0) < 20)
            {
                for (var row = 0; row < ShapeArray.GetLength(0); row++)
                {
                    for (var col = 0; col < ShapeArray.GetLength(1); col++)
                    {
                        if (this.ShapeArray[row, col])
                            if (GridData[Top + row + 1, Left + col])
                                return true;
                    }
                }
            }
            return Top + ShapeArray.GetLength(0) == 20;
        }
    }
}
